﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.Utilities;
using File = Microsoft.SharePoint.Client.File;
using System.Net;
using System.IO;
using System.Collections;

namespace CustomControls
{
    public class SharepointHelper
    {

        //http://dotnetbyexample.blogspot.com/2011/03/sharepoint-client-object-model-sites.html
        //http://msdn.microsoft.com/en-us/library/ee535228.aspx

        private ClientContext clientContext;
        private Web rootWeb;

        public SharepointHelper(string url, string username, string password, string domain)
        {
            clientContext = new ClientContext(url);
            var credentials = new NetworkCredential(username, password, domain);
            clientContext.Credentials = credentials;
            rootWeb = clientContext.Web;
            clientContext.Load(rootWeb);
        }

        public SharepointHelper(string url)
        {
            clientContext = new ClientContext(url);
            clientContext.Credentials = System.Net.CredentialCache.DefaultCredentials;
            rootWeb = clientContext.Web;
            clientContext.Load(rootWeb);
        }

        public void CreateSite(string siteDescription, string siteTitle, string siteUrl)
        {
            rootWeb = rootWeb.Webs.Add(new WebCreationInformation
            {
                Description = siteDescription,
                Title = siteTitle,
                Url = siteUrl,
                UseSamePermissionsAsParentSite = false
            });
            clientContext.ExecuteQuery();
        }

        public List<Web> GetSites()
        {
            //int qtde = rootWeb.Webs.Count;
            var projetos = clientContext.LoadQuery(rootWeb.Webs);
            clientContext.ExecuteQuery();
            return projetos.ToList<Web>();
        }

        public List<List> GetLists(string siteTitle)
        {
            var web = GetWebByTitle(siteTitle);
            var lists = web.Lists;
            clientContext.Load(lists);
            clientContext.ExecuteQuery();
            return lists.ToList<List>();
        }

        public Web GetWebByTitle(string siteTitle)
        {
            var query = clientContext.LoadQuery(rootWeb.Webs.Where(p => p.Title == siteTitle));
            clientContext.ExecuteQuery();
            return query.FirstOrDefault();
        }

        private RoleDefinition GetRole(string siteTitle, RoleType rType)
        {
            var web = GetWebByTitle(siteTitle);
            if (web != null)
            {
                var roleDefs = web.RoleDefinitions;
                var query = clientContext.LoadQuery(roleDefs.Where(p => p.RoleTypeKind == rType));
                clientContext.ExecuteQuery();
                return query.FirstOrDefault();
            }
            return null;
        }

        public Principal GetPrincipal(string name, string siteTitle)
        {
            var web = GetWebByTitle(siteTitle);
            if (web != null)
            {
                try
                {
                    var principal = web.EnsureUser(name);
                    clientContext.Load(principal);
                    clientContext.ExecuteQuery();
                    if (principal != null)
                    {
                        return principal;
                    }
                }
                catch (ServerException) { }
            }
            return null;
        }

        public List GetDocumentLibrary(string siteTitle, string libraryName)
        {
            var web = GetWebByTitle(siteTitle);
            if (web != null)
            {
                var query = clientContext.LoadQuery(
                     web.Lists.Where(p => p.Title == libraryName));
                clientContext.ExecuteQuery();
                return query.FirstOrDefault();
            }
            return null;
        }

        public ListTemplate GetDocumentLibraryTemplate(Web web, string name)
        {
            ListTemplateCollection ltc = web.ListTemplates;
            var listTemplates = clientContext.LoadQuery(
              ltc.Where(p => p.InternalName == name));
            clientContext.Load(ltc);
            clientContext.ExecuteQuery();
            return listTemplates.FirstOrDefault();
        }

        public bool CreateDocumentLibrary(string siteTitle, string libraryName, string libraryDescription, string userGroup)
        {
            var web = GetWebByTitle(siteTitle);
            if (web != null)
            {
                // First load all the list
                var lists = web.Lists;
                clientContext.Load(lists);
                clientContext.ExecuteQuery();

                // Create new lib based upon the doclib template
                var newList = lists.Add(new ListCreationInformation
                {
                    Title = libraryName,
                    Description = libraryDescription,
                    TemplateType = GetDocumentLibraryTemplate(web, "doclib").ListTemplateTypeKind,
                    QuickLaunchOption = QuickLaunchOptions.On
                });
                clientContext.ExecuteQuery();

                // Override default permission inheritance
                newList.BreakRoleInheritance(false, false);

                // Get principal for usergroup and the contributor role
                var principal = GetPrincipal(userGroup, siteTitle);
                var role = GetRole(siteTitle, RoleType.Contributor);

                // Add the role to the collection.
                var collRdb = new RoleDefinitionBindingCollection(clientContext) { role };
                var collRoleAssign = newList.RoleAssignments;
                collRoleAssign.Add(principal, collRdb);

                clientContext.ExecuteQuery();

                return true;
            }
            return false;
        }

        public List<ListPermissions> GetPermissionLibrary(string siteTitle, string libraryName)
        {
            List<ListPermissions> lst = new List<ListPermissions>();

            //recupera o site
            var web = GetWebByTitle(siteTitle);

            //recupera a lista
            var lista = GetDocumentLibrary(siteTitle, libraryName);

            if (lista != null)
            {
                // carrega as roles da lista
                clientContext.Load(lista.RoleAssignments);
                clientContext.ExecuteQuery();

                // recuperar cada membro
                foreach (var role in lista.RoleAssignments)
                {
                    string permissionLevel = string.Empty;

                    Principal membro = role.Member;
                    clientContext.Load(membro);
                    clientContext.ExecuteQuery();

                    RoleDefinitionBindingCollection coll = role.RoleDefinitionBindings;
                    clientContext.Load(coll);
                    clientContext.ExecuteQuery();

                    foreach (var item in coll)
                    {
                        permissionLevel = item.Name;
                    }

                    ListPermissions perm = new ListPermissions();
                    perm.UserName = membro.LoginName;
                    perm.LevelPermission = permissionLevel;
                    perm.TypeAccount = membro.PrincipalType.ToString();
                    lst.Add(perm);
                }
            }

            return lst;
        }

        public bool SetPermissionSite(string siteTitle, string userGroup)
        {
            var site = GetWebByTitle(siteTitle);

            if (site != null)
            {
                // Override default permission inheritance
                site.BreakRoleInheritance(false, false);

                // Get principal for usergroup and the contributor role
                var principal = GetPrincipal(userGroup, siteTitle);
                var role = GetRole(siteTitle, RoleType.Contributor);

                // Add the role to the collection.
                var collRdb = new RoleDefinitionBindingCollection(clientContext) { role };
                var collRoleAssign = site.RoleAssignments;
                collRoleAssign.Add(principal, collRdb);

                clientContext.ExecuteQuery();

                return true;
            }

            return false;
        }

        public bool SetPermissionSite(string siteTitle, string userGroup, RoleType roleType)
        {
            var site = GetWebByTitle(siteTitle);

            if (site != null)
            {
                // Override default permission inheritance
                site.BreakRoleInheritance(false, false);

                // Get principal for usergroup and the contributor role
                var principal = GetPrincipal(userGroup, siteTitle);
                var role = GetRole(siteTitle, roleType);

                // Add the role to the collection.
                var collRdb = new RoleDefinitionBindingCollection(clientContext) { role };
                var collRoleAssign = site.RoleAssignments;
                collRoleAssign.Add(principal, collRdb);

                clientContext.ExecuteQuery();

                return true;
            }

            return false;
        }

        public bool SetPermissionLibrary(string siteTitle, string libraryName, string userGroup)
        {
            var lista = GetDocumentLibrary(siteTitle, libraryName);

            if (lista != null)
            {
                // Override default permission inheritance
                lista.BreakRoleInheritance(false, false);

                // Get principal for usergroup and the contributor role
                var principal = GetPrincipal(userGroup, siteTitle);
                var role = GetRole(siteTitle, RoleType.Contributor);

                // Add the role to the collection.
                var collRdb = new RoleDefinitionBindingCollection(clientContext) { role };
                var collRoleAssign = lista.RoleAssignments;
                collRoleAssign.Add(principal, collRdb);

                clientContext.ExecuteQuery();

                return true;
            }

            return false;
        }

        public bool SetPermissionLibrary(string siteTitle, string libraryName, string userGroup, RoleType roleType)
        {
            var lista = GetDocumentLibrary(siteTitle, libraryName);

            if (lista != null)
            {
                // Override default permission inheritance
                lista.BreakRoleInheritance(false, false);

                // Get principal for usergroup and the contributor role
                var principal = GetPrincipal(userGroup, siteTitle);
                var role = GetRole(siteTitle, roleType);

                // Add the role to the collection.
                var collRdb = new RoleDefinitionBindingCollection(clientContext) { role };
                var collRoleAssign = lista.RoleAssignments;
                collRoleAssign.Add(principal, collRdb);

                clientContext.ExecuteQuery();

                return true;
            }

            return false;
        }

        public void CreateFolder(string siteTitle, string libraryName, string folder)
        {
            var list = GetDocumentLibrary(siteTitle, libraryName);
            if (list != null)
            {
                var folders = list.RootFolder.Folders;
                clientContext.Load(folders);
                clientContext.ExecuteQuery();
                var newFolder = folders.Add(folder);
                clientContext.ExecuteQuery();
            }
        }

        public void UploadDocument(string siteTitle, string libraryName, string fileName)
        {
            var web = GetWebByTitle(siteTitle);
            var fInfo = new FileInfo(fileName);
            var targetLocation = string.Format("{0}/{1}/{2}", web.ServerRelativeUrl,
               libraryName, fInfo.Name);

            using (var fs = new FileStream(fileName, FileMode.Open))
            {
                File.SaveBinaryDirect(clientContext, targetLocation, fs, true);
            }
        }

        public void DownloadDocument(string siteTitle, string libraryName, string fileName)
        {
            var web = GetWebByTitle(siteTitle);
            var fInfo = new FileInfo(fileName);

            var source = string.Format("{0}/{1}/{2}", web.ServerRelativeUrl,
                                                      libraryName, fInfo.Name);
            var spFileInfo = File.OpenBinaryDirect(clientContext, source);
            using (var fs = new FileStream(fileName, FileMode.OpenOrCreate))
            {
                //spFileInfo.Stream.CopyTo(fs);
            }
        }

        public List<File> ListFiles(string siteTitle, string libraryName)
        {
            var list = GetDocumentLibrary(siteTitle, libraryName);
            var files = list.RootFolder.Files;
            clientContext.Load(files);
            clientContext.ExecuteQuery();
            return files.ToList();
        }

        public List<Folder> ListFolders(string siteTitle, string libraryName)
        {
            var list = GetDocumentLibrary(siteTitle, libraryName);
            var folders = list.RootFolder.Folders;
            clientContext.Load(folders);
            clientContext.ExecuteQuery();
            return folders.ToList();
        }

        public List<Folder> ListSubFolders(string siteTitle, string serverRelativeUrl)
        {
            var web = GetWebByTitle(siteTitle);
            var folders = web.GetFolderByServerRelativeUrl(serverRelativeUrl).Folders;
            clientContext.Load(folders);
            clientContext.ExecuteQuery();
            return folders.ToList();

        }

        public List<File> ListFilesFolder(string siteTitle, string serverRelativeUrl)
        {
            var web = GetWebByTitle(siteTitle);
            var files = web.GetFolderByServerRelativeUrl(serverRelativeUrl).Files;
            clientContext.Load(files);
            clientContext.ExecuteQuery();
            return files.ToList();
        }
    }

    public class ListPermissions
    {
        public string UserName { get; set; }
        public string LevelPermission { get; set; }
        public string TypeAccount { get; set; }
    }
}
